serverless deployで何が更新されるのか確認してみました(Serverless Framework / AWS)
はじめに
Serverless FrameworkをAWS環境に対してサービスの作成・更新・削除で利用する場合に、実際にはどのAWSサービスのリソースが変更されているのか、というのがなんとなくわかっていたけど曖昧だったのと、実際に動かしてみたくなったため、各コマンドについて動かしつつ整理してみることにしました。
前提
- 作業環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G4032
- 執筆時点で最新(Latest release: 1.68.0)のバージョンでの動作を確認しています
- AWSで利用する場合 について記載しています
- AWS CLIの結果をターミナル上で整形するためにjqを利用しています
まとめ
やってみた結果は次の通りでした。
コマンド | CloudFormationスタック | それ以外(Lambda, API Gateway, S3, etc...) |
---|---|---|
1. deploy | 更新する | 更新する※ |
2. deploy function | 更新しない | 更新する |
3. remove | 更新する | 更新する※ |
※注 スタックの更新に伴い間接的に更新
ちなみに、service名+stage名がスタック名として自動設定されるため、同じservice名&同じstageで同じリージョンに対するserverless.ymlを作ると以前の設定が上書きされるので要注意です。(定義していないリソースは、消えます。)
やってみたこと
やってみた結果わかったことは「まとめ」のセクションに書いたとおりですが、実際に確認したプロセスを記載します。
サービスの新規作成
1. テンプレートからサービスを作成
作業用ディレクトリを作成して、その中に新規サービスをテンプレートから作成します
$ mkdir app $ cd app $ serverless create --template aws-nodejs
2. -v オプションを付けてデプロイ実行してログを追ってみる
deployコマンドに -v
を付けて実行します。
リソースの作成に関係しそうな部分としては以下の表示がありました。
$ serverless deploy -v
CloudFormation - CREATE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket CloudFormation - CREATE_COMPLETE - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - app-dev Serverless: Uploading CloudFormation file to S3... Serverless: Uploading service app.zip file to S3 (389 B)... CloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - HelloLogGroup CloudFormation - CREATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution CloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction CloudFormation - CREATE_COMPLETE - AWS::Lambda::Version - HelloLambdaVersionWmPiX0uxnqMasoXkiuYJx9ARiVG14cpohy5OECjVrA
ここからやっぱりCloudFormationを使ってバケットとかビルド成果物のアップロード等を行っているんだな、ということは分かりました。
3. 生成されたリソースを整理してみる
2.で作成されたリソースに加え、ローカルにも中間ファイルが作成されています。 それらも含めて整理すると、deployコマンド実行後は次のようなリソースが出来上がっていました。
- 作業マシン側
- コードのzip
- 内部的に使うCloudFormationテンプレート
- 他
- AWS側
- CloudFormationスタック
- デプロイ中間ファイル配置用S3バケット
- LambdaのIAMロール
- Lambdaのロググループ
- Lambdaのfunction
サービスの更新
更新パターンについて
サービスの更新を行うパターンは次の2つがあります。
- serverless deploy
- serverless deploy function
serverless deploy
コマンドによる更新は「サービスの新規作成」のセクションで記述した挙動と同じでCloudFormationスタックの更新が行われますが、serverless deploy functionを実行する場合にはスタックの更新は行われません。
Serverless Framework Commands - AWS Lambda - Deploy Function https://serverless.com/framework/docs/providers/aws/cli-reference/deploy-function/
The sls deploy function command deploys an individual function without AWS CloudFormation
serverless deploy function
による更新をやってみた
1. ソースを修正
handler.jsの出力メッセージ部分を編集します。 「Go Serverless〜」という文言を「Goo Serverless」に編集します。
$ sed -n 8p handler.js message: 'Go Serverless v1.0! Your function executed successfully!!', $ sed -i '' '8s/Go/Goo/' handler.js $ sed -n 8p handler.js message: 'Goo Serverless v1.0! Your function executed successfully!!',
2. デプロイ
serverless deploy function
によって指定した関数のみをデプロイします。
- デプロイ前にスタックの更新時刻を確認
$ aws cloudformation describe-stacks --stack-name app-dev --region us-east-1 | jq .Stacks[].LastUpdatedTime "2020-04-27T14:01:14.579Z"
- デプロイ実行
$ sls deploy function --function hello Serverless: Packaging function: hello... (中略) Serverless: Successfully updated function: hello
- デプロイ後にスタックの更新時刻を確認
$ aws cloudformation describe-stacks --stack-name app-dev --region us-east-1 | jq .Stacks[].LastUpdatedTime "2020-04-27T14:01:14.579Z"
serverless deploy function
前後で確認したスタックの更新時刻から、スタックは更新されていないことが分かります。
serverless deploy
による更新
新規作成時と同じ挙動なので、確認したプロセスは割愛します。
サービスの削除
serverless remove
によってリソースを削除してみました。
なるべく内部の挙動を確認したかったので -v
を付けて実行しました。
$ sls remove -v : CloudFormation - DELETE_COMPLETE - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy : CloudFormation - DELETE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction : Serverless: Stack removal finished...
removeコマンドの実行結果からは、CloudFormationを通じてS3のデプロイメントバケットやLambda関数が削除されたことを確認できました。
$ aws cloudformation list-stack-resources --stack-name app-dev --region us-east-1 An error occurred (ValidationError) when calling the ListStackResources operation: Stack with id app-dev does not exist
スタックが削除されていることも確認できました。
サービス名が同じで、リソースの定義が違うセットを用意します。「サービスの新規作成」「サービスの更新」で用意したディレクトリをコピーして、関数名だけ変更したものを用意しました。
$ cp -r app app2
$ vim app2/serverless.yml
$ diff app app2 diff app/serverless.yml app2/serverless.yml 61c61 < hello: --- > hello2:
まず1つ目のディレクトリで serverless deploy
を行います
$ cd app $ sls deploy
次に、2つめのディレクトリでは -v
オプションを付けて serverless deploy
を行います
$ cd app2 $ sls deploy -v
すると、stack名が同じ(service名とstage名が同じ)であるため、「hello」関数の定義が差分として検出され、削除されました
CloudFormation - DELETE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunction CloudFormation - DELETE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunction
この状態で1つめのディレクトリへ移動して serverless remove
コマンドを実行してみます( -v
オプションを付けて )
$ cd app $ sls remove -v
すると、2つめのディレクトリ内で定義していた関数もすべて削除されました。
CloudFormation - DELETE_COMPLETE - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy : CloudFormation - DELETE_COMPLETE - AWS::Lambda::Function - Hello2LambdaFunction
つまり、service名とstage名が同じ組み合わせのファイルを別々に作成すると、片方の設定が最新として処理されるため注意が必要です。
参考
- Serverless Framework Documentation https://www.serverless.com/framework/docs/